package edu.hm.vss.producerConsumer;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author yasser
 */
public class Producer implements Runnable {

    private final int localProcessID;
    private final Buffer data;
    private boolean stopRequested = false;

    public Producer(int localProcessID, Buffer data) {
        this.localProcessID = localProcessID;
        this.data = data;
    }

    public int getProcessID() {
        return this.localProcessID;
    }

    public boolean canProduce() {
        return data.getSize() < Buffer.MAX_INDEX;
    }

    public void produceItem() {
        Object item = new Object();
        System.out.printf("Producer (%s) producing (%s) ...\n", Thread.currentThread().getName(), item);
        data.add(item);
        System.out.printf("List size : %s\n", data.getList().size());
        System.out.printf("%s \n\n", data.getList());
        data.incCounter();;
    }

    @Override
    public String toString() {
        return "Producer " + this.localProcessID;
    }

    @Override
    public void run() {
        while (!data.stopRequested()) {
            synchronized (data.getList()) {

                if (data.getList().size() == Buffer.MIN_INDEX) {
                    System.out.printf("Producer (%s) sending signal ...\n", Thread.currentThread().getName());
                    data.getList().notifyAll();
                }

                while (!data.stopRequested() && !canProduce()) {
                    try {
                        System.out.printf("Producer (%s) waiting ...\n", Thread.currentThread().getName());
                        data.getList().wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Producer.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }

                produceItem();
                if (data.stopRequested()) {
                    data.getList().notifyAll();
                    return;
                }

            }
            try {
                // sleep for some time, 
                Thread.sleep(10);
            } catch (InterruptedException e) {
            }
        }


    }
}
